/**
 * Copyright 2009 Henning Teek, Ingo Renner
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.googlecode.bricket.web.common.modal;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.googlecode.bricket.domain.DataFileContainer;
import com.googlecode.bricket.domain.DomainObject;
import com.googlecode.bricket.repository.StorehouseService;
import com.googlecode.bricket.web.common.ActionPanelBuilder;
import com.googlecode.bricket.web.common.DeleteActionLink;
import com.googlecode.bricket.web.common.DownloadActionLink;
import com.googlecode.bricket.web.common.EditActionLink;
import com.googlecode.bricket.web.common.table.AjaxFallbackDefaultDataTableBuilder;
import com.googlecode.bricket.web.common.table.ListDataProvider;
import com.googlecode.bricket.web.util.ComponentUtil;

public abstract class APresenterPanel<T extends DomainObject> extends Panel {
	private final static Logger log = LoggerFactory.getLogger(APresenterPanel.class);

	@SpringBean
	private StorehouseService storehouseService;

    private final AModalManagement<T> manager;
	private Component presentation;

	public APresenterPanel(String id,	AModalManagement<T> manager) {
		super(id);
		this.manager = manager;
		add(getPresentation());
		setOutputMarkupId(true);
	}
	
	/**
	 * 
	 * @param property
	 * @return SimpleclassnameOfModel.property
	 */
	private String addPrefixToProperty(String property) {
		return manager.getNewObject().getClass().getSimpleName() + "." + property;
	}
	
	public Component getAddLink(String id) {
        AjaxLink<Void> createLink = new AjaxLink<Void>(id) {
            public void onClick(AjaxRequestTarget target) {
                try {
                    prepareAdd(target);
                    manager.getFreshCurrentObject();
                    manager.setEditMode(false);
                    manager.getEditor().show(target);
                } catch (Exception e) {
                    getSession().error(e.getMessage());
                    Component fp = ComponentUtil.getComponentByClass(getPage(), FeedbackPanel.class);
                    if (fp != null) {
                        target.addComponent(fp);
                    }
                }
            }
        };
        createLink.setOutputMarkupId(true);
		createLink.setVisible(isEditable());
		return createLink;
	}
	
	protected abstract void prepareAdd(AjaxRequestTarget target);

	protected Component getPresentation() {
		if (presentation == null) {
			final String id = "table";
			AjaxFallbackDefaultDataTableBuilder builder =  AjaxFallbackDefaultDataTableBuilder.getBuilder(manager.getPresenterParent())
			.addDataProvider(new ListDataProvider<T>(manager.getValues()));
			if (isEditable() || isDelete()) {
				builder.add(new AbstractColumn<Object>(new StringResourceModel(addPrefixToProperty("actions.label"), manager.getPresenterParent(), null)) {
					@Override
					public void populateItem(final Item cellItem, String componentId, IModel rowModel) {
						final ActionPanelBuilder linkBuilder = ActionPanelBuilder.getBuilder();
						final IModel<T> component = new Model<T>((T) rowModel.getObject());
						// Eintrag editieren
						if (isEditable()) {
							linkBuilder.add(new EditActionLink(true) {
								@Override
								public void onClick(AjaxRequestTarget target) {
									manager.setCurrentObject(component.getObject());
									manager.setEditMode(true);
									final AModalWindow<T> ce = manager.getEditor();
									ce.show(target);
								}
							});						
							if (rowModel.getObject() instanceof DataFileContainer) {
								DataFileContainer dfc = (DataFileContainer) rowModel.getObject(); 
								linkBuilder.add(new DownloadActionLink(dfc.getFilename(), storehouseService.getDataFile(dfc.getHash())));
							}
						}
						if (isDelete()) {
							DeleteActionLink removeLink = new DeleteActionLink(new StringResourceModel(addPrefixToProperty("actions.delete.confirm"), manager.getPresenterParent(), null), true) {
								@Override
								public void onClick(AjaxRequestTarget target) {
									prepareRemove(target, component.getObject());
									manager.getValues().remove(component.getObject());
									cellItem.modelChanged();
									target.addComponent(getPresentation());
									removeDone(target, component.getObject());
								}
							};
							linkBuilder.add(removeLink);
						}
						cellItem.add(linkBuilder.build(componentId));
					}
				});
			}
			addColumns(builder);
			presentation =  builder.build(id);
		} else {
			presentation.modelChanged();
		}
		return presentation;
	}

	protected abstract void prepareRemove(AjaxRequestTarget target, T object);

	protected abstract void removeDone(AjaxRequestTarget target, T object);

	protected abstract void addColumns(AjaxFallbackDefaultDataTableBuilder builder);

	/**
	 * 
	 * @return true if edit is allowed
	 */
	protected boolean isEditable() {
		return manager.isEditMode();
	}
	
	protected boolean isDelete() {
		return manager.isDelete();
	}
}
